﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;

namespace Microsoft.Services.NuGet.Server.Infrastructure
{
    public class BuildFileSystem
        : IFileSystem
    {
        private ILogger _logger;

        public ILogger Logger
        {
            get
            {
                return _logger ?? NullLogger.Instance;
            }
            set
            {
                _logger = value;
            }
        }

        public virtual string GetFullPath(string path)
        {
            return path;
        }

        public virtual void AddFile(string path, Stream stream)
        {
            throw new NotSupportedException();
        }

        public virtual void DeleteFile(string path)
        {
            throw new NotSupportedException();
        }

        public virtual void DeleteDirectory(string path)
        {
            throw new NotSupportedException();
        }

        public virtual void DeleteDirectory(string path, bool recursive)
        {
            throw new NotSupportedException();
        }

        public virtual IEnumerable<string> GetFiles(string path)
        {
            return GetFiles(path, "*.*");
        }

        public virtual IEnumerable<string> GetFiles(string path, string filter)
        {
            path = EnsureTrailingSlash(GetFullPath(path));
            try
            {
                if (!Directory.Exists(path))
                {
                    return Enumerable.Empty<string>();
                }
                return Directory.EnumerateFiles(path, filter)
                                .Select(MakeRelativePath);
            }
            catch (UnauthorizedAccessException)
            {

            }
            catch (DirectoryNotFoundException)
            {

            }

            return Enumerable.Empty<string>();
        }

        public virtual IEnumerable<string> GetDirectories(string path)
        {
            try
            {
                path = EnsureTrailingSlash(GetFullPath(path));
                if (!Directory.Exists(path))
                {
                    return Enumerable.Empty<string>();
                }
                return Directory.EnumerateDirectories(path)
                                .Select(MakeRelativePath);
            }
            catch (UnauthorizedAccessException)
            {

            }
            catch (DirectoryNotFoundException)
            {

            }

            return Enumerable.Empty<string>();
        }

        public virtual DateTimeOffset GetLastModified(string path)
        {
            if (DirectoryExists(path))
            {
                return new DirectoryInfo(GetFullPath(path)).LastWriteTimeUtc;
            }
            return new FileInfo(GetFullPath(path)).LastWriteTimeUtc;
        }

        public DateTimeOffset GetCreated(string path)
        {
            if (DirectoryExists(path))
            {
                return Directory.GetCreationTimeUtc(GetFullPath(path));
            }
            return File.GetCreationTimeUtc(GetFullPath(path));
        }

        public virtual bool FileExists(string path)
        {
            path = GetFullPath(path);
            return File.Exists(path);
        }

        public virtual bool DirectoryExists(string path)
        {
            path = GetFullPath(path);
            return Directory.Exists(path);
        }

        public virtual Stream OpenFile(string path)
        {
            path = GetFullPath(path);
            return File.OpenRead(path);
        }

        protected string MakeRelativePath(string fullPath)
        {
            return fullPath;
        }

        private void EnsureDirectory(string path)
        {
            path = GetFullPath(path);
            Directory.CreateDirectory(path);
        }

        private static string EnsureTrailingSlash(string path)
        {
            if (!path.EndsWith("\\", StringComparison.Ordinal))
            {
                path += "\\";
            }
            return path;
        }

        public string Root
        {
            get { return null; }
        }
    }
}
